# -*- coding:utf-8 -*-


from fastapi import APIRouter, Depends, HTTPException, Security, Request, BackgroundTasks

from core.response import success_page, ResponsePage, ResponseModel, success
from core.dependencies import page_filter

from app.models.request.user import User, UserCreate, UserUpdate, UserRoleIn, UserRole
from app.models.request.role import Role
from app.repository.user import UserRepository
from app.service.auth import password_hash
from app.service.user import check_login_user, UserService

from app.service.verify import generate_link, verify_link
from app.service.email import send_message, Email

from app.logger import getLogger

logger = getLogger()

router = APIRouter(prefix="/user")

@router.get("/", response_model=ResponsePage[User], summary="用户列表查询", dependencies=[Security(check_login_user, scopes=["user_access"])])
async def pages(pageNo: int=1, pageSize: int=10
        , page_filter = Depends(page_filter)
        , repo: UserRepository = Depends(UserRepository)):
    data, total_page, total_rows = await repo.get_by_page(pageNo, pageSize, page_filter)
    return success_page(page_no=pageNo, page_size=pageSize, total_page = total_page, total_rows=total_rows, data=data)


@router.get("/{id}/info", response_model=ResponseModel[User], summary="用户信息查询", dependencies=[Security(check_login_user, scopes=["user_access"])])
async def user_by_id(id: int, service: UserService = Depends(UserService)):
    db_user = await service.get_user_by_id(id)
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    return success(data=User.from_orm(db_user))


@router.get("/info", response_model=ResponseModel[User], summary="当前用户信息", dependencies=[Security(check_login_user)])
async def user_info(request: Request, service: UserService = Depends(UserService)):
    db_user = await service.get_user_by_id(request.state.user_id, request.app.state.redis)
    return success(data=User.from_orm(db_user))


@router.post("/register", response_model=ResponseModel[User], summary="用户注册")
async def do_register(user: UserCreate, request: Request, tasks: BackgroundTasks, repo: UserRepository = Depends(UserRepository)):
    check_user = await repo.get_user_by_username(user.account)
    if check_user is not None:
        raise HTTPException(status_code=400, detail="User already exists")
    check_user = await repo.get_user_by_email(user.email)
    if check_user is not None:
        raise HTTPException(status_code=400, detail="User already exists")
    check_user = await repo.get_user_by_mobile(user.mobile)
    if check_user is not None:
        raise HTTPException(status_code=400, detail="User already exists")
    
    user.password = password_hash(user.password)
    another={'status': 0}
    if user.invite_code:
        # 检查邀请码是否有效,如果有效则将邀请码对应的用户id存入user表中
        another['status'] = 1
    create_user=request.state.user_id if hasattr(request.state, "user_id") else None
    user = await repo.save(user, another=another, create_user=create_user)
    
    link = await generate_link(user.email)
    # 将token存入redis
    # 发送邮件
    tasks.add_task(send_message, Email(subject="激活账号", addresses=[user.email], content=link))
    return success(data=User.from_orm(user))


@router.get("/activate/{token}", response_model=ResponseModel[str], summary="激活账号")
async def activate_email(token: str, repo: UserRepository = Depends(UserRepository)):
    data = await verify_link(token)
    email = data.get('email', None)
    if email is None:
        raise HTTPException(status_code=400, detail="Invalid token")
    check_data = (await repo.get_filter(filter={"email": email})).first()
    if check_data is None:
        raise HTTPException(status_code=400, detail="account not found")
    await repo.update(check_data.id, User.from_orm({'status': 1}), update_user='-1')
    # TODO: 激活账号
    return success(data=email, message="激活成功")

@router.post("/", response_model=ResponseModel[User], summary="用户创建", dependencies=[Security(check_login_user, scopes=["user_create"])])
async def do_create_user(user: UserCreate, request: Request, repo: UserRepository = Depends(UserRepository)):
    check_user = await repo.get_user_by_username(user.account)
    if check_user is not None:
        raise HTTPException(status_code=400, detail="User already exists")
    check_user = await repo.get_user_by_email(user.email)
    if check_user is not None:
        raise HTTPException(status_code=400, detail="User already exists")
    check_user = await repo.get_user_by_mobile(user.mobile)
    if check_user is not None:
        raise HTTPException(status_code=400, detail="User already exists")
    
    user.password = password_hash(user.password)
    user = await repo.save(user, create_user=request.state.user_id if hasattr(request.state, "user_id") else None)
    return success(data=User.from_orm(user))

@router.delete("/{id}", response_model=ResponseModel[User], summary="用户删除", dependencies=[Security(check_login_user, scopes=["user_delete"])])
async def do_delete_user(id: int, request: Request, repo: UserRepository = Depends(UserRepository)):
    db_user = await repo.get_by_id(id)
    if db_user is None:
        raise HTTPException(status_code=400, detail="User not found")
    user = await repo.delete(id, delete_user=request.state.user_id)
    # 删除用户缓存
    await request.app.state.redis.delete(f"user:{user.id}")
    return success(data=User.from_orm(user))

@router.put("/{id}", response_model=ResponseModel[User], summary="用户信息修改", dependencies=[Security(check_login_user, scopes=["user_update"])])
async def do_update_user(id: int, user: UserUpdate, request: Request, repo: UserRepository = Depends(UserRepository)):
    check_user = await repo.get_by_id(id)
    if check_user is None:
        raise HTTPException(status_code=400, detail="User not found")
    user = await repo.update(id, user, update_user=request.state.user_id)
    # 更新缓存
    await request.app.state.redis.set(f"user_id:{id}", json.dumps(user.single_to_dict()), ex=60)
    return success(data=User.from_orm(user))

@router.get("/{id}/roles", response_model=ResponseModel[UserRole], summary="用户角色查询", dependencies=[Security(check_login_user, scopes=["user_role_access"])])
async def user_roles_by_id(id: int, repo: UserRepository = Depends(UserRepository)):
    check_user = await repo.get_by_id(id)
    if check_user is None:
        raise HTTPException(status_code=400, detail="User not found")
    
    check_user.roles = (await repo.get_ref_by_ids([id], "tb_role", "user_role", Role))[id]
    return success(data=UserRole.from_orm(check_user))

@router.put("/{id}/roles", response_model=ResponseModel[UserRole], summary="用户角色修改", dependencies=[Security(check_login_user, scopes=["user_role_update"])])
async def do_update_user_roles(id: int, data: UserRoleIn, request: Request, repo: UserRepository = Depends(UserRepository)):
    check_user = await repo.get_by_id(id)
    if check_user is None:
        raise HTTPException(status_code=400, detail="User not found")
    
    if data.roles is not None:
        role_ids = [role.id for role in (await repo.get_ref_by_ids([id], "tb_role", "user_role", Role))[id]]
        logger.info(f"roles: {data.roles}, role_ids: {role_ids}")
        
        delete_role_ids = [id for id in role_ids if int(id) not in data.roles]
        logger.info(f"delete_role_ids: {delete_role_ids}")
        await repo.delete_ref(id, delete_role_ids, "tb_role", "user_role", delete_user=request.state.user_id)
        # 验证新增的权限是否合法
        add_role_ids = [id for id in data.roles if str(id) not in role_ids]
        logger.info(f"add_role_ids: {add_role_ids}")
        await repo.add_ref(id, add_role_ids, "tb_role", "user_role", request.state.user_id)
    
    check_user.roles = (await repo.get_ref_by_ids([id], "tb_role", "user_role", Role))[id]
    return success(data=UserRole.from_orm(check_user))
